#include "transmit.h"
#include <sys/sendfile.h>

int sendInfo(int netfd, void *data, int size)
{
    train_t train;
    // 发文件名
    bzero(train.data, sizeof(train.data));
    train.length = size;
    memcpy(train.data, data, train.length);
    send(netfd, &train, sizeof(train.length) + train.length, 0);
    return 0;
}

// 获取车头长度，并将内容读取到buf
int recvInfo(int netfd, void *buf)
{
    train_t train;
    bzero(&train, sizeof(train));
    int ret = recv(netfd, &train.length, sizeof(int), 0);
    ERROR_CHECK(ret, -1, "recv");
    if (ret == 0)
        return 0;
    recvPhase(netfd, buf, train.length);
    return ret;
}

// 读到length个字符才会结束循环
int recvPhase(int netfd, void *buf, int length)
{
    int total = 0; // 存储已经读取了多少个字节
    int ret;
    char *p = (char *)buf; // 一个char一个字节
    while (total < length)
    {
        ret = recv(netfd, p + total, length - total, 0);
        ERROR_CHECK(ret, -1, "recv");
        total += ret;
    }
    return 0;
}

int sepFilename(char *filepath, char *filename)
{
    int i = 0;
    while (*(filepath + i))
    {
        if (*(filepath + i) == '/')
        {
            filepath = filepath + i + 1;
            i = 0;
        }
        i++;
    }
    strncpy(filename, filepath, i);
}

int sendFilename(int netfd, char *filePath){
    puts(filePath);
    train_t train;
    // 发文件名
    bzero(train.data, sizeof(train.data));
    char filename[128] = {0};
    sepFilename(filePath, filename);
    train.length = strlen(filename);
    memcpy(train.data, filename, strlen(filename));
    //puts(train.data);
    send(netfd, &train, sizeof(train.length) + train.length, 0);
}

int sendFile(int netfd, char *filePath)
{
    train_t train;
    bzero(train.data, sizeof(train.data));
    // 服务端先获取文件的大小 把文件大小装入小火车
    int fd = open(filePath, O_RDWR);
    // 发文件长度
    struct stat statbuf;
    fstat(fd, &statbuf);
    bzero(&train, sizeof(train));
    train.length = sizeof(statbuf.st_size);
    memcpy(train.data, &statbuf.st_size, sizeof(statbuf.st_size)); // 获得文件长度
    send(netfd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);

    // 直接sendfile
    sendfile(netfd, fd, NULL, statbuf.st_size);
    return statbuf.st_size;
}

int recvFilename(int netfd,char *filename)
{
    train_t train;
    bzero(&train, sizeof(train));
    recv(netfd, &train.length, sizeof(int), MSG_WAITALL);
    recv(netfd, train.data, train.length, MSG_WAITALL);
    strcpy(filename,train.data);
}

int recvFile(int netfd, char *savePath, char *filename)
{
    char filepath[2048] = {0};
    sprintf(filepath, "%s/%s", savePath, filename);
    puts(filepath);
    int fd = open(filepath, O_RDWR | O_CREAT, 0666);
    off_t filesize;
    train_t train;
    bzero(train.data, sizeof(train.data));
    //接受长度
    recv(netfd, &train.length, sizeof(int), 0);
    recv(netfd, train.data, train.length, 0);
    memcpy(&filesize, train.data, train.length);
    printf("filesize = %ld\n", filesize);

    // 一次性接收
    ftruncate(fd, filesize);
    char *p = (char *)mmap(NULL, filesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    ERROR_CHECK(p, MAP_FAILED, "mmap");
    recvPhase(netfd, p, filesize); // 一次性收了一个文件的内容
    munmap(p, filesize);
    close(fd);
    return filesize;
}